home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / global_edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-02-12  |  22.0 KB  |  958 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <glib.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "drawable.h"
  30. #include "image_new.h"
  31. #include "floating_sel.h"
  32. #include "gdisplay.h"
  33. #include "gimage.h"
  34. #include "gimage_mask.h"
  35. #include "gimprc.h"
  36. #include "gimpui.h"
  37. #include "global_edit.h"
  38. #include "layer.h"
  39. #include "paint_funcs.h"
  40. #include "tools.h"
  41. #include "undo.h"
  42.  
  43. #include "libgimp/gimpintl.h"
  44.  
  45. #include "tile_manager_pvt.h"
  46. #include "drawable_pvt.h"
  47.  
  48. typedef enum
  49. {
  50.   PASTE,
  51.   PASTE_INTO,
  52.   PASTE_AS_NEW
  53. } PasteAction;  
  54.  
  55. /*  The named paste dialog  */
  56. typedef struct _PasteNamedDlg PasteNamedDlg;
  57.  
  58. struct _PasteNamedDlg
  59. {
  60.   GtkWidget   *shell;
  61.   GtkWidget   *list;
  62.   GDisplay    *gdisp;
  63.   PasteAction  action;
  64. };
  65.  
  66. /*  The named buffer structure...  */
  67. typedef struct _named_buffer NamedBuffer;
  68.  
  69. struct _named_buffer
  70. {
  71.   TileManager *buf;
  72.   gchar       *name;
  73. };
  74.  
  75.  
  76. /*  The named buffer list  */
  77. static GSList *named_buffers = NULL;
  78.  
  79. /*  The global edit buffer  */
  80. TileManager   *global_buf = NULL;
  81.  
  82.  
  83. /*  Crop the buffer to the size of pixels with non-zero transparency */
  84.  
  85. TileManager *
  86. crop_buffer (TileManager *tiles,
  87.          gboolean     border)
  88. {
  89.   PixelRegion  PR;
  90.   TileManager *new_tiles;
  91.   gint         bytes, alpha;
  92.   guchar      *data;
  93.   gint         empty;
  94.   gint         x1, y1, x2, y2;
  95.   gint         x, y;
  96.   gint         ex, ey;
  97.   gint         found;
  98.   void        *pr;
  99.   guchar       black[MAX_CHANNELS] = { 0, 0, 0, 0 };
  100.  
  101.   bytes = tiles->bpp;
  102.   alpha = bytes - 1;
  103.  
  104.   /*  go through and calculate the bounds  */
  105.   x1 = tiles->width;
  106.   y1 = tiles->height;
  107.   x2 = 0;
  108.   y2 = 0;
  109.  
  110.   pixel_region_init (&PR, tiles, 0, 0, x1, y1, FALSE);
  111.   for (pr = pixel_regions_register (1, &PR); pr != NULL; pr = pixel_regions_process (pr))
  112.     {
  113.       data = PR.data + alpha;
  114.       ex = PR.x + PR.w;
  115.       ey = PR.y + PR.h;
  116.  
  117.       for (y = PR.y; y < ey; y++)
  118.     {
  119.       found = FALSE;
  120.       for (x = PR.x; x < ex; x++, data+=bytes)
  121.         if (*data)
  122.           {
  123.         if (x < x1)
  124.           x1 = x;
  125.         if (x > x2)
  126.           x2 = x;
  127.         found = TRUE;
  128.           }
  129.       if (found)
  130.         {
  131.           if (y < y1)
  132.         y1 = y;
  133.           if (y > y2)
  134.         y2 = y;
  135.         }
  136.     }
  137.     }
  138.  
  139.   x2 = CLAMP (x2 + 1, 0, tiles->width);
  140.   y2 = CLAMP (y2 + 1, 0, tiles->height);
  141.  
  142.   empty = (x1 == tiles->width && y1 == tiles->height);
  143.  
  144.   /*  If there are no visible pixels, return NULL */
  145.   if (empty)
  146.     new_tiles = NULL;
  147.   /*  If no cropping, return original buffer  */
  148.   else if (x1 == 0 && y1 == 0 && x2 == tiles->width &&
  149.        y2 == tiles->height && border == 0)
  150.     new_tiles = tiles;
  151.   /*  Otherwise, crop the original area  */
  152.   else
  153.     {
  154.       PixelRegion srcPR, destPR;
  155.       int new_width, new_height;
  156.  
  157.       new_width = (x2 - x1) + border * 2;
  158.       new_height = (y2 - y1) + border * 2;
  159.       new_tiles = tile_manager_new (new_width, new_height, bytes);
  160.  
  161.       /*  If there is a border, make sure to clear the new tiles first  */
  162.       if (border)
  163.     {
  164.       pixel_region_init (&destPR, new_tiles, 0, 0, new_width, border, TRUE);
  165.       color_region (&destPR, black);
  166.       pixel_region_init (&destPR, new_tiles, 0, border, border, (y2 - y1), TRUE);
  167.       color_region (&destPR, black);
  168.       pixel_region_init (&destPR, new_tiles, new_width - border, border, border, (y2 - y1), TRUE);
  169.       color_region (&destPR, black);
  170.       pixel_region_init (&destPR, new_tiles, 0, new_height - border, new_width, border, TRUE);
  171.       color_region (&destPR, black);
  172.     }
  173.  
  174.       pixel_region_init (&srcPR, tiles, x1, y1, (x2 - x1), (y2 - y1), FALSE);
  175.       pixel_region_init (&destPR, new_tiles, border, border, (x2 - x1), (y2 - y1), TRUE);
  176.  
  177.       copy_region (&srcPR, &destPR);
  178.  
  179.       new_tiles->x = x1;
  180.       new_tiles->y = y1;
  181.     }
  182.  
  183.   return new_tiles;
  184. }
  185.  
  186. TileManager *
  187. edit_cut (GImage       *gimage,
  188.       GimpDrawable *drawable)
  189. {
  190.   TileManager *cut;
  191.   TileManager *cropped_cut;
  192.   gint         empty;
  193.  
  194.   if (!gimage || drawable == NULL)
  195.     return NULL;
  196.  
  197.   /*  Start a group undo  */
  198.   undo_push_group_start (gimage, EDIT_CUT_UNDO);
  199.  
  200.   /*  See if the gimage mask is empty  */
  201.   empty = gimage_mask_is_empty (gimage);
  202.  
  203.   /*  Next, cut the mask portion from the gimage  */
  204.   cut = gimage_mask_extract (gimage, drawable, TRUE, FALSE, TRUE);
  205.  
  206.   /*  Only crop if the gimage mask wasn't empty  */
  207.   if (cut && empty == FALSE)
  208.     {
  209.       cropped_cut = crop_buffer (cut, 0);
  210.  
  211.       if (cropped_cut != cut)
  212.     tile_manager_destroy (cut);
  213.     }
  214.   else if (cut)
  215.     cropped_cut = cut;
  216.   else
  217.     cropped_cut = NULL;
  218.  
  219.   if (cut)
  220.     image_new_reset_current_cut_buffer ();
  221.  
  222.  
  223.   /*  end the group undo  */
  224.   undo_push_group_end (gimage);
  225.  
  226.   if (cropped_cut)
  227.     {
  228.       /*  Free the old global edit buffer  */
  229.       if (global_buf)
  230.     tile_manager_destroy (global_buf);
  231.       /*  Set the global edit buffer  */
  232.       global_buf = cropped_cut;
  233.  
  234.       return cropped_cut;
  235.     }
  236.   else
  237.     return NULL;
  238. }
  239.  
  240. TileManager *
  241. edit_copy (GImage       *gimage,
  242.        GimpDrawable *drawable)
  243. {
  244.   TileManager *copy;
  245.   TileManager *cropped_copy;
  246.   gint         empty;
  247.  
  248.   if (!gimage || drawable == NULL)
  249.     return NULL;
  250.  
  251.   /*  See if the gimage mask is empty  */
  252.   empty = gimage_mask_is_empty (gimage);
  253.  
  254.   /*  First, copy the masked portion of the gimage  */
  255.   copy = gimage_mask_extract (gimage, drawable, FALSE, FALSE, TRUE);
  256.  
  257.   /*  Only crop if the gimage mask wasn't empty  */
  258.   if (copy && empty == FALSE)
  259.     {
  260.       cropped_copy = crop_buffer (copy, 0);
  261.  
  262.       if (cropped_copy != copy)
  263.     tile_manager_destroy (copy);
  264.     }
  265.   else if (copy)
  266.     cropped_copy = copy;
  267.   else
  268.     cropped_copy = NULL;
  269.  
  270.   if(copy)
  271.     image_new_reset_current_cut_buffer();
  272.  
  273.  
  274.   if (cropped_copy)
  275.     {
  276.       /*  Free the old global edit buffer  */
  277.       if (global_buf)
  278.     tile_manager_destroy (global_buf);
  279.       /*  Set the global edit buffer  */
  280.       global_buf = cropped_copy;
  281.  
  282.       return cropped_copy;
  283.     }
  284.   else
  285.     return NULL;
  286. }
  287.  
  288. GimpLayer *
  289. edit_paste (GImage       *gimage,
  290.         GimpDrawable *drawable,
  291.         TileManager  *paste,
  292.         gboolean      paste_into)
  293. {
  294.   Layer *layer;
  295.   gint   x1, y1, x2, y2;
  296.   gint   cx, cy;
  297.  
  298.   /*  Make a new layer: iff drawable == NULL,
  299.    *  user is pasting into an empty display.
  300.    */
  301.  
  302.   if (drawable != NULL)
  303.     layer = layer_new_from_tiles (gimage,
  304.                   gimp_drawable_type_with_alpha (drawable),
  305.                   paste, 
  306.                   _("Pasted Layer"),
  307.                   OPAQUE_OPACITY, NORMAL_MODE);
  308.   else
  309.     layer = layer_new_from_tiles (gimage,
  310.                   gimp_image_base_type_with_alpha (gimage),
  311.                   paste, 
  312.                   _("Pasted Layer"),
  313.                   OPAQUE_OPACITY, NORMAL_MODE);
  314.  
  315.   if (layer)
  316.     {
  317.       /*  Start a group undo  */
  318.       undo_push_group_start (gimage, EDIT_PASTE_UNDO);
  319.  
  320.       /*  Set the offsets to the center of the image  */
  321.       if (drawable != NULL)
  322.     {
  323.       drawable_offsets (drawable, &cx, &cy);
  324.       drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  325.       cx += (x1 + x2) >> 1;
  326.       cy += (y1 + y2) >> 1;
  327.     }
  328.       else
  329.     {
  330.       cx = gimage->width >> 1;
  331.       cy = gimage->height >> 1;
  332.     }
  333.  
  334.       GIMP_DRAWABLE (layer)->offset_x = cx - (GIMP_DRAWABLE (layer)->width >> 1);
  335.       GIMP_DRAWABLE (layer)->offset_y = cy - (GIMP_DRAWABLE (layer)->height >> 1);
  336.  
  337.       /*  If there is a selection mask clear it--
  338.        *  this might not always be desired, but in general,
  339.        *  it seems like the correct behavior.
  340.        */
  341.       if (! gimage_mask_is_empty (gimage) && !paste_into)
  342.     channel_clear (gimage_get_mask (gimage));
  343.  
  344.       /*  if there's a drawable, add a new floating selection  */
  345.       if (drawable != NULL)
  346.     {
  347.       floating_sel_attach (layer, drawable);
  348.     }
  349.       else
  350.     {
  351.       gimp_drawable_set_gimage (GIMP_DRAWABLE (layer), gimage);
  352.       gimage_add_layer (gimage, layer, 0);
  353.     }
  354.       
  355.      /*  end the group undo  */
  356.       undo_push_group_end (gimage);
  357.  
  358.       return layer;
  359.     }
  360.  
  361.   return NULL;
  362. }
  363.  
  364. gboolean
  365. edit_paste_as_new (GImage      *invoke,
  366.            TileManager *paste)
  367. {
  368.   GImage   *gimage;
  369.   Layer    *layer;
  370.   GDisplay *gdisp;
  371.   GimpParasite *comment_parasite;
  372.  
  373.   if (!global_buf)
  374.     return FALSE;
  375.  
  376.   /*  create a new image  (always of type RGB)  */
  377.   gimage = gimage_new (paste->width, paste->height, RGB);
  378.   gimage_disable_undo (gimage);
  379.   gimp_image_set_resolution (gimage, invoke->xresolution, invoke->yresolution);
  380.   gimp_image_set_unit (gimage, invoke->unit);
  381.   
  382.   if (default_comment)
  383.     {
  384.       comment_parasite = gimp_parasite_new ("gimp-comment",
  385.                         GIMP_PARASITE_PERSISTENT,
  386.                         strlen (default_comment) + 1,
  387.                         (gpointer) default_comment);
  388.       gimp_image_parasite_attach (gimage, comment_parasite);
  389.       gimp_parasite_free (comment_parasite);
  390.     }
  391.   
  392.   layer = layer_new_from_tiles (gimage,
  393.                 gimp_image_base_type_with_alpha (gimage),
  394.                 paste, 
  395.                 _("Pasted Layer"),
  396.                 OPAQUE_OPACITY, NORMAL_MODE);
  397.  
  398.   if (layer)
  399.     {
  400.       /*  add the new layer to the image  */
  401.       gimp_drawable_set_gimage (GIMP_DRAWABLE (layer), gimage);
  402.       gimage_add_layer (gimage, layer, 0);
  403.  
  404.       gimage_enable_undo (gimage);
  405.  
  406.       gdisp = gdisplay_new (gimage, 0x0101);
  407.       gimp_context_set_display (gimp_context_get_user (), gdisp);
  408.  
  409.       return TRUE;
  410.     }
  411.  
  412.   return FALSE;                   
  413. }
  414.  
  415. gboolean
  416. edit_clear (GImage       *gimage,
  417.         GimpDrawable *drawable)
  418. {
  419.   TileManager *buf_tiles;
  420.   PixelRegion  bufPR;
  421.   gint         x1, y1, x2, y2;
  422.   guchar       col[MAX_CHANNELS];
  423.  
  424.   if (!gimage || drawable == NULL)
  425.     return FALSE;
  426.  
  427.   gimage_get_background (gimage, drawable, col);
  428.   if (drawable_has_alpha (drawable))
  429.     col [drawable_bytes (drawable) - 1] = OPAQUE_OPACITY;
  430.  
  431.   drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  432.  
  433.   if (!(x2 - x1) || !(y2 - y1))
  434.     return TRUE;  /*  nothing to do, but the clear succeded  */
  435.  
  436.   buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), drawable_bytes (drawable));
  437.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  438.   color_region (&bufPR, col);
  439.  
  440.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
  441.   gimage_apply_image (gimage, drawable, &bufPR, 1, OPAQUE_OPACITY,
  442.               ERASE_MODE, NULL, x1, y1);
  443.  
  444.   /*  update the image  */
  445.   drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
  446.  
  447.   /*  free the temporary tiles  */
  448.   tile_manager_destroy (buf_tiles);
  449.  
  450.   return TRUE;
  451. }
  452.  
  453. gboolean
  454. edit_fill (GImage       *gimage,
  455.        GimpDrawable *drawable,
  456.        GimpFillType  fill_type)
  457. {
  458.   TileManager *buf_tiles;
  459.   PixelRegion  bufPR;
  460.   gint         x1, y1, x2, y2;
  461.   guchar       col[MAX_CHANNELS];
  462.  
  463.   if (!gimage || drawable == NULL)
  464.     return FALSE;
  465.  
  466.   if (drawable_has_alpha (drawable))
  467.     col [drawable_bytes (drawable) - 1] = OPAQUE_OPACITY;
  468.  
  469.   switch (fill_type)
  470.     {
  471.     case FOREGROUND_FILL:
  472.       gimage_get_foreground (gimage, drawable, col);
  473.       break;
  474.  
  475.     case BACKGROUND_FILL:
  476.       gimage_get_background (gimage, drawable, col);
  477.       break;
  478.  
  479.     case WHITE_FILL:
  480.       col[RED_PIX] = 255;
  481.       col[GREEN_PIX] = 255;
  482.       col[BLUE_PIX] = 255;
  483.       break;
  484.  
  485.     case TRANSPARENT_FILL:
  486.       col[RED_PIX] = 0;
  487.       col[GREEN_PIX] = 0;
  488.       col[BLUE_PIX] = 0;
  489.       if (drawable_has_alpha (drawable))
  490.     col [drawable_bytes (drawable) - 1] = TRANSPARENT_OPACITY;
  491.       break;
  492.  
  493.     case NO_FILL:
  494.       return TRUE;  /*  nothing to do, but the fill succeded  */
  495.  
  496.     default:
  497.       g_warning ("unknown fill type");
  498.       gimage_get_background (gimage, drawable, col);
  499.       break;
  500.     }
  501.  
  502.   drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  503.  
  504.   if (!(x2 - x1) || !(y2 - y1))
  505.     return TRUE;  /*  nothing to do, but the fill succeded  */
  506.  
  507.   buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), drawable_bytes (drawable));
  508.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  509.   color_region (&bufPR, col);
  510.  
  511.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
  512.   gimage_apply_image (gimage, drawable, &bufPR, 1, OPAQUE_OPACITY,
  513.               NORMAL_MODE, NULL, x1, y1);
  514.  
  515.   /*  update the image  */
  516.   drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
  517.  
  518.   /*  free the temporary tiles  */
  519.   tile_manager_destroy (buf_tiles);
  520.  
  521.   return TRUE;
  522. }
  523.  
  524. gboolean
  525. global_edit_cut (GDisplay *gdisp)
  526. {
  527.   /*  stop any active tool  */
  528.   active_tool_control (HALT, gdisp);
  529.  
  530.   if (!edit_cut (gdisp->gimage, gimage_active_drawable (gdisp->gimage)))
  531.     return FALSE;
  532.  
  533.   /*  flush the display  */
  534.   gdisplays_flush ();
  535.  
  536.   return TRUE;
  537. }
  538.  
  539. gboolean
  540. global_edit_copy (GDisplay *gdisp)
  541. {
  542.   if (!edit_copy (gdisp->gimage, gimage_active_drawable (gdisp->gimage)))
  543.     return FALSE;
  544.  
  545.   return TRUE;
  546. }
  547.  
  548. gboolean
  549. global_edit_paste (GDisplay *gdisp,
  550.            gboolean  paste_into)
  551. {
  552.   /*  stop any active tool  */
  553.   active_tool_control (HALT, gdisp);
  554.  
  555.   if (!edit_paste (gdisp->gimage, gimage_active_drawable (gdisp->gimage), 
  556.            global_buf, paste_into))
  557.     return FALSE;
  558.  
  559.   /*  flush the display  */
  560.   gdisplays_update_title (gdisp->gimage);
  561.   gdisplays_flush ();
  562.  
  563.   return TRUE;
  564. }
  565.  
  566. gboolean
  567. global_edit_paste_as_new (GDisplay *gdisp)
  568. {
  569.   if (!global_buf)
  570.     return FALSE;
  571.  
  572.   /*  stop any active tool  */
  573.   active_tool_control (HALT, gdisp);
  574.  
  575.   return edit_paste_as_new (gdisp->gimage, global_buf);
  576. }
  577.  
  578. void
  579. global_edit_free (void)
  580. {
  581.   if (global_buf)
  582.     tile_manager_destroy (global_buf);
  583.  
  584.   global_buf = NULL;
  585. }
  586.  
  587. /*********************************************/
  588. /*        Named buffer operations            */
  589.  
  590. static void
  591. set_list_of_named_buffers (GtkWidget *list_widget)
  592. {
  593.   GSList      *list;
  594.   NamedBuffer *nb;
  595.   GtkWidget   *list_item;
  596.  
  597.   gtk_list_clear_items (GTK_LIST (list_widget), 0, -1);
  598.  
  599.   for (list = named_buffers; list; list = g_slist_next (list))
  600.     {
  601.       nb = (NamedBuffer *) list->data;
  602.  
  603.       list_item = gtk_list_item_new_with_label (nb->name);
  604.       gtk_container_add (GTK_CONTAINER (list_widget), list_item);
  605.       gtk_object_set_user_data (GTK_OBJECT (list_item), (gpointer) nb);
  606.       gtk_widget_show (list_item);
  607.     }
  608. }
  609.  
  610. static void
  611. named_buffer_paste_foreach (GtkWidget *widget,
  612.                 gpointer   data)
  613. {
  614.   PasteNamedDlg *pn_dlg;
  615.   NamedBuffer   *nb;
  616.  
  617.   if (widget->state == GTK_STATE_SELECTED)
  618.     {
  619.       pn_dlg = (PasteNamedDlg *) data;
  620.       nb     = (NamedBuffer *) gtk_object_get_user_data (GTK_OBJECT (widget));
  621.  
  622.       switch (pn_dlg->action)
  623.     {
  624.     case PASTE:
  625.       edit_paste (pn_dlg->gdisp->gimage,
  626.               gimage_active_drawable (pn_dlg->gdisp->gimage),
  627.               nb->buf, FALSE);
  628.       break;
  629.  
  630.     case PASTE_INTO:
  631.       edit_paste (pn_dlg->gdisp->gimage,
  632.               gimage_active_drawable (pn_dlg->gdisp->gimage),
  633.               nb->buf, TRUE);
  634.       break;
  635.  
  636.     case PASTE_AS_NEW:
  637.       edit_paste_as_new (pn_dlg->gdisp->gimage, nb->buf);
  638.       break;
  639.  
  640.     default:
  641.       break;
  642.     }
  643.     }
  644. }
  645.  
  646. static void
  647. named_buffer_paste_callback (GtkWidget *widget,
  648.                  gpointer   data)
  649. {
  650.   PasteNamedDlg *pn_dlg;
  651.  
  652.   pn_dlg = (PasteNamedDlg *) data;
  653.  
  654.   pn_dlg->action = PASTE_INTO;
  655.   gtk_container_foreach ((GtkContainer *) pn_dlg->list,
  656.              named_buffer_paste_foreach, data);
  657.  
  658.   /*  Destroy the box  */
  659.   gtk_widget_destroy (pn_dlg->shell);
  660.  
  661.   g_free (pn_dlg);
  662.       
  663.   /*  flush the display  */
  664.   gdisplays_flush ();
  665. }
  666.  
  667. static void
  668. named_buffer_paste_into_callback (GtkWidget *widget,
  669.                   gpointer   data)
  670. {
  671.   PasteNamedDlg *pn_dlg;
  672.  
  673.   pn_dlg = (PasteNamedDlg *) data;
  674.  
  675.   pn_dlg->action = PASTE_INTO;
  676.   gtk_container_foreach ((GtkContainer *) pn_dlg->list,
  677.              named_buffer_paste_foreach, data);
  678.  
  679.   /*  Destroy the box  */
  680.   gtk_widget_destroy (pn_dlg->shell);
  681.  
  682.   g_free (pn_dlg);
  683.       
  684.   /*  flush the display  */
  685.   gdisplays_flush ();
  686. }
  687.  
  688. static void
  689. named_buffer_paste_as_new_callback (GtkWidget *widget,
  690.                     gpointer   data)
  691. {
  692.   PasteNamedDlg *pn_dlg;
  693.  
  694.   pn_dlg = (PasteNamedDlg *) data;
  695.  
  696.   pn_dlg->action = PASTE_AS_NEW;
  697.   gtk_container_foreach ((GtkContainer *) pn_dlg->list,
  698.              named_buffer_paste_foreach, data);
  699.  
  700.   /*  Destroy the box  */
  701.   gtk_widget_destroy (pn_dlg->shell);
  702.  
  703.   g_free (pn_dlg);
  704.       
  705.   /*  flush the display  */
  706.   gdisplays_flush ();
  707. }
  708.  
  709. static void
  710. named_buffer_delete_foreach (GtkWidget *widget,
  711.                  gpointer   data)
  712. {
  713.   PasteNamedDlg *pn_dlg;
  714.   NamedBuffer   *nb;
  715.  
  716.   if (widget->state == GTK_STATE_SELECTED)
  717.     {
  718.       pn_dlg = (PasteNamedDlg *) data;
  719.       nb     = (NamedBuffer *) gtk_object_get_user_data (GTK_OBJECT (widget));
  720.  
  721.       named_buffers = g_slist_remove (named_buffers, (void *) nb);
  722.       g_free (nb->name);
  723.       tile_manager_destroy (nb->buf);
  724.       g_free (nb);
  725.     }
  726. }
  727.  
  728. static void
  729. named_buffer_delete_callback (GtkWidget *widget,
  730.                   gpointer   data)
  731. {
  732.   PasteNamedDlg *pn_dlg;
  733.  
  734.   pn_dlg = (PasteNamedDlg *) data;
  735.  
  736.   gtk_container_foreach ((GtkContainer*) pn_dlg->list,
  737.              named_buffer_delete_foreach, data);
  738.   set_list_of_named_buffers (pn_dlg->list);
  739. }
  740.  
  741. static void
  742. named_buffer_cancel_callback (GtkWidget *widget,
  743.                   gpointer   data)
  744. {
  745.   PasteNamedDlg *pn_dlg;
  746.  
  747.   pn_dlg = (PasteNamedDlg *) data;
  748.  
  749.   /*  Destroy the box  */
  750.   gtk_widget_destroy (pn_dlg->shell);
  751.  
  752.   g_free (pn_dlg);
  753. }
  754.  
  755. static void
  756. paste_named_buffer (GDisplay *gdisp)
  757. {
  758.   PasteNamedDlg *pn_dlg;
  759.   GtkWidget *vbox;
  760.   GtkWidget *label;
  761.   GtkWidget *listbox;
  762.   GtkWidget *bbox;
  763.   GtkWidget *button;
  764.   gint i;
  765.  
  766.   static gchar *paste_action_labels[] =
  767.   {
  768.     N_("Paste"),
  769.     N_("Paste Into"),
  770.     N_("Paste as New"),
  771.   };
  772.  
  773.   static GtkSignalFunc paste_action_functions[] =
  774.   {
  775.     named_buffer_paste_callback,
  776.     named_buffer_paste_into_callback,
  777.     named_buffer_paste_as_new_callback,
  778.   };
  779.  
  780.   pn_dlg = g_new (PasteNamedDlg, 1);
  781.   pn_dlg->gdisp = gdisp;
  782.  
  783.   pn_dlg->shell =
  784.     gimp_dialog_new (_("Paste Named Buffer"), "paste_named_buffer",
  785.              gimp_standard_help_func,
  786.              "dialogs/paste_named.html",
  787.              GTK_WIN_POS_MOUSE,
  788.              FALSE, TRUE, FALSE,
  789.  
  790.              _("Delete"), named_buffer_delete_callback,
  791.              pn_dlg, NULL, NULL, FALSE, FALSE,
  792.              _("Cancel"), named_buffer_cancel_callback,
  793.              pn_dlg, NULL, NULL, TRUE, TRUE,
  794.  
  795.              NULL);
  796.              
  797.   vbox = gtk_vbox_new (FALSE, 1);
  798.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 1);
  799.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (pn_dlg->shell)->vbox), vbox);
  800.   gtk_widget_show (vbox);
  801.  
  802.   label = gtk_label_new (_("Select a buffer to paste:"));
  803.   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
  804.   gtk_widget_show (label);
  805.  
  806.   listbox = gtk_scrolled_window_new (NULL, NULL);
  807.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (listbox),
  808.                   GTK_POLICY_AUTOMATIC,
  809.                   GTK_POLICY_AUTOMATIC);
  810.   gtk_box_pack_start (GTK_BOX (vbox), listbox, TRUE, TRUE, 0);
  811.   gtk_widget_set_usize (listbox, 125, 150);
  812.   gtk_widget_show (listbox);
  813.  
  814.   pn_dlg->list = gtk_list_new ();
  815.   gtk_list_set_selection_mode (GTK_LIST (pn_dlg->list), GTK_SELECTION_BROWSE);
  816.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (listbox),
  817.                      pn_dlg->list);
  818.   set_list_of_named_buffers (pn_dlg->list);
  819.   gtk_widget_show (pn_dlg->list);
  820.  
  821.   bbox = gtk_hbutton_box_new ();
  822.   gtk_container_set_border_width (GTK_CONTAINER (bbox), 6);
  823.   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 2);
  824.   gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
  825.   for (i = 0; i < 3; i++)
  826.     {
  827.       button = gtk_button_new_with_label (gettext (paste_action_labels[i]));
  828.       gtk_container_add (GTK_CONTAINER (bbox), button);
  829.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  830.               (GtkSignalFunc) paste_action_functions[i],
  831.               pn_dlg);
  832.       gtk_widget_show (button);
  833.     }
  834.   gtk_widget_show (bbox);
  835.  
  836.   gtk_widget_show (pn_dlg->shell);
  837. }
  838.  
  839. static void
  840. new_named_buffer (TileManager *tiles,
  841.           gchar       *name)
  842. {
  843.   PixelRegion srcPR, destPR;
  844.   NamedBuffer *nb;
  845.  
  846.   if (! tiles) return;
  847.  
  848.   nb = (NamedBuffer *) g_malloc (sizeof (NamedBuffer));
  849.  
  850.   nb->buf = tile_manager_new (tiles->width, tiles->height, tiles->bpp);
  851.   pixel_region_init (&srcPR, tiles, 0, 0, tiles->width, tiles->height, FALSE);
  852.   pixel_region_init (&destPR, nb->buf, 0, 0, tiles->width, tiles->height, TRUE);
  853.   copy_region (&srcPR, &destPR);
  854.  
  855.   if (! (name && strlen (name)))
  856.     name = _("(Unnamed Buffer)");
  857.  
  858.   nb->name = g_strdup (name);
  859.   named_buffers = g_slist_append (named_buffers, (void *) nb);
  860. }
  861.  
  862. static void
  863. cut_named_buffer_callback (GtkWidget *widget,
  864.                gchar     *name,
  865.                gpointer   data)
  866. {
  867.   TileManager *new_tiles;
  868.   GDisplay    *gdisp;
  869.  
  870.   gdisp = (GDisplay *) data;
  871.  
  872.   new_tiles = edit_cut (gdisp->gimage, gimage_active_drawable (gdisp->gimage));
  873.   if (new_tiles) 
  874.     new_named_buffer (new_tiles, name);
  875.   gdisplays_flush ();
  876. }
  877.  
  878. gboolean
  879. named_edit_cut (GDisplay *gdisp)
  880. {
  881.   GtkWidget *qbox;
  882.  
  883.   /*  stop any active tool  */
  884.   active_tool_control (HALT, gdisp);
  885.  
  886.   qbox = gimp_query_string_box (_("Cut Named"),
  887.                 gimp_standard_help_func,
  888.                 "dialogs/cut_named.html",
  889.                 _("Enter a name for this buffer"),
  890.                 NULL,
  891.                 GTK_OBJECT (gdisp->gimage), "destroy",
  892.                 cut_named_buffer_callback, gdisp);
  893.   gtk_widget_show (qbox);
  894.  
  895.   return TRUE;
  896. }
  897.  
  898. static void
  899. copy_named_buffer_callback (GtkWidget *widget,
  900.                 gchar     *name,
  901.                 gpointer   data)
  902. {
  903.   TileManager *new_tiles;
  904.   GDisplay    *gdisp;
  905.  
  906.   gdisp = (GDisplay *) data;
  907.   
  908.   new_tiles = edit_copy (gdisp->gimage, gimage_active_drawable (gdisp->gimage));
  909.   if (new_tiles) 
  910.     new_named_buffer (new_tiles, name);
  911. }
  912.  
  913. gboolean
  914. named_edit_copy (GDisplay *gdisp)
  915. {
  916.   GtkWidget *qbox;
  917.  
  918.   qbox = gimp_query_string_box (_("Copy Named"),
  919.                 gimp_standard_help_func,
  920.                 "dialogs/copy_named.html",
  921.                 _("Enter a name for this buffer"),
  922.                 NULL,
  923.                 GTK_OBJECT (gdisp->gimage), "destroy",
  924.                 copy_named_buffer_callback, gdisp);
  925.   gtk_widget_show (qbox);
  926.  
  927.   return TRUE;
  928. }
  929.  
  930. gboolean
  931. named_edit_paste (GDisplay *gdisp)
  932. {
  933.   paste_named_buffer (gdisp);
  934.  
  935.   gdisplays_flush ();
  936.  
  937.   return TRUE;
  938. }
  939.  
  940. void
  941. named_buffers_free (void)
  942. {
  943.   GSList      *list;
  944.   NamedBuffer *nb;
  945.  
  946.   for (list = named_buffers; list; list = g_slist_next (list))
  947.     {
  948.       nb = (NamedBuffer *) list->data;
  949.  
  950.       tile_manager_destroy (nb->buf);
  951.       g_free (nb->name);
  952.       g_free (nb);
  953.     }
  954.  
  955.   g_slist_free (named_buffers);
  956.   named_buffers = NULL;
  957. }
  958.